package net.gldwork.srcpdr;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

public class SourceProducer {
	public static final String PUBLIC = "public";
	public static final String PRIVATE = "private";
	public static final String PROTECTED = "protected";

	private String name;
	private String extendsClassName;
	private List<String> interfaces = new LinkedList<String>();
	private List<Field> fields = new LinkedList<Field>();
	private List<Method> methods = new LinkedList<Method>();
	private List<String> imports = new LinkedList<String>();
	private List<String> annotations = new LinkedList<String>();
	private String packageName;

	public String getQualifiedName() {
		return packageName + "." + name;
	}

	public SourceProducer(String className) {
		this.name = className;
	}

	public SourceProducer() {

	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void removeFieldByName(String fieldName) {
		for (Iterator<Field> it = fields.iterator(); it.hasNext();) {
			Field f = it.next();
			if (f.getParamName().equals(fieldName)) {
				it.remove();
			}
		}
	}

	public void removeMethodByPrefix(String prefix) {
		for (Iterator<Method> it = methods.iterator(); it.hasNext();) {
			Method m = it.next();
			if (m.getName().startsWith(prefix)) {
				it.remove();
			}
		}
	}

	public SourceProducer addAnnotation(String anno) {

		if (!annotations.contains(anno)) {
			annotations.add(anno);
		}

		return this;
	}

	public SourceProducer addImport(String importString) {
		if (!imports.contains(importString))
			imports.add(importString);
		return this;
	}

	public boolean containsImport(String importString) {
		return imports.contains(importString);
	}

	public SourceProducer setPackage(String packageString) {
		this.packageName = packageString;
		return this;
	}

	public SourceProducer setExtends(String extendClassName) {
		this.extendsClassName = extendClassName;
		return this;
	}

	public SourceProducer addImplements(String interfaceName) {
		if (!interfaces.contains(interfaceName))
			interfaces.add(interfaceName);
		return this;
	}

	public SourceProducer addField(Field field) {

		if (!fields.contains(field)) {
			fields.add(field);
		}

		return this;
	}

	public SourceProducer addMethod(Method method) {
		methods.add(method);
		return this;
	}

	private ContentBlock toContentBlock() {
		ContentBlock cb = new ContentBlock();
		StringBuffer sb = new StringBuffer();
		sb.append("package ").append(packageName).append(";");
		cb.addLine(sb.toString());
		cb.addBlankLine();

		for (String ip : imports) {
			sb = new StringBuffer();
			sb.append("import ").append(ip).append(";");
			cb.addLine(sb.toString());
		}
		cb.addBlankLine();
		for (String anno : annotations) {
			cb.addLine(anno);
		}

		sb = new StringBuffer();
		sb.append("public class ").append(name).append(" ");
		if (extendsClassName != null) {
			sb.append("extends ").append(extendsClassName).append(" ");
		}
		if (interfaces.size() > 0) {
			sb.append("implements ").append(StringUtils.join(interfaces, ","))
					.append(" ");
		}
		sb.append("{");
		cb.addLine(sb.toString());
		cb.addBlankLine();
		for (Field field : fields) {
			cb.append(field.toContentBlock(), 1);

		}
		cb.addBlankLine();
		for (Method method : methods) {
			cb.append(method.toContentBlock(), 1);
			cb.addBlankLine();
		}
		cb.addLine("}");
		return cb;
	}

	public String toString() {
		return toContentBlock().toString();
	}

}
